using Engine.Graphics;
using SharpDX;
using System;
using System.IO;

using MyEngine = Engine.Graphics;

namespace Engine.FileFormats3D.C11Syndikat.QADFile
{
    public struct C11Surface
    {
        #region Internal Fields

        internal short data1;
        internal short data2;
        internal short data3;
        internal short data4;
        internal short mappingMode;
        internal short texture1ID;
        internal short texture2ID;
        internal short texture3ID;

        #endregion Internal Fields

        #region Private Fields

        private uint data5;
        private uint data6;
        private int hashcode;

        //public Mappings mappings1;
        //public Mappings mappings2;
        //public Mappings mappings3;
        private Matrix mappingMatrix3x3;

        private long positionInFile;

        #endregion Private Fields

        #region Public Constructors

        public C11Surface(MyEngine.Material material, MaterialManager materialManager)
        {
            {
                throw new NotImplementedException("C11 syndicate plugin must created!");
                //this.texture1ID = (short)materialManager.GetTextureID(material.TextureName1);
                //this.texture2ID = (short)materialManager.GetTextureID(material.TextureName2);
                //this.texture3ID = (short)materialManager.GetTextureID(material.TextureName3);
            }

            this.data1 = 0xFF;
            this.data2 = 0xFF;
            this.data3 = 0xFF;
            this.data4 = 0xFF;
            throw new NotImplementedException("Mapping Mode form C11 Materiel");
            // this.mappingMode = (short)material.GameMaterialProperties.MappingMode;
            this.mappingMatrix3x3 = Matrix.Identity;
            //this.mappingMatrix3x3.M11 = matrix1;
            //this.mappingMatrix3x3.M12 = matrix2;
            //this.mappingMatrix3x3.M13 = matrix3;
            //this.mappingMatrix3x3.M21 = matrix4;
            //this.mappingMatrix3x3.M22 = matrix5;
            //this.mappingMatrix3x3.M23 = matrix6;
            //this.mappingMatrix3x3.M31 = matrix7;
            //this.mappingMatrix3x3.M32 = matrix8;
            //this.mappingMatrix3x3.M33 = matrix9;

            this.data5 = 0;
            this.data6 = 0;
            this.positionInFile = 0;
            hashcode = 0;
            UpdateHashCode();
        }

        public C11Surface(short textureId1, short textureId2, short textureId3, short data1,
            short data2, short data3, short data4, short mappingMode, float matrix1, float matrix2,
            float matrix3, float matrix4, float matrix5, float matrix6, float matrix7, float matrix8,
            float matrix9, uint data5, uint data6)
        {
            this.positionInFile = 0;

            this.texture1ID = textureId1;
            this.texture2ID = textureId2;
            this.texture3ID = textureId3;
            this.data1 = data1;
            this.data2 = data2;
            this.data3 = data3;
            this.data4 = data4;
            this.mappingMode = mappingMode;
            this.mappingMatrix3x3 = Matrix.Identity;
            this.mappingMatrix3x3.M11 = matrix1;
            this.mappingMatrix3x3.M12 = matrix2;
            this.mappingMatrix3x3.M13 = matrix3;
            this.mappingMatrix3x3.M21 = matrix4;
            this.mappingMatrix3x3.M22 = matrix5;
            this.mappingMatrix3x3.M23 = matrix6;
            this.mappingMatrix3x3.M31 = matrix7;
            this.mappingMatrix3x3.M32 = matrix8;
            this.mappingMatrix3x3.M33 = matrix9;

            this.data5 = data5;
            this.data6 = data6;
            this.hashcode = 0;
            this.
            UpdateHashCode();
        }

        #endregion Public Constructors

        #region Public Methods

        public static C11Surface FromStream(BinaryReader br)
        {
            long positionInFile = br.BaseStream.Position;

            C11Surface surface = new C11Surface(
                br.ReadInt16(), // tex1
                br.ReadInt16(), // tex2
                br.ReadInt16(), // tex3
                br.ReadInt16(), // data
                br.ReadInt16(), // data
                br.ReadInt16(), // data
                br.ReadInt16(), // data
                br.ReadInt16(), // mappingMode
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadSingle(),// matrix
                br.ReadUInt32(), // data
                br.ReadUInt32()); // data
            surface.positionInFile = positionInFile;
            return surface;
        }

        public override int GetHashCode()
        {
            return this.hashcode;
        }

        public MyEngine.Material ToMaterial(MaterialManager materialManager)
        {
            if (this.texture1ID > materialManager.TextureNames.Count - 1)
                this.texture1ID = 0;
            if (this.texture2ID > materialManager.TextureNames.Count - 1)
                this.texture2ID = 0;
            if (this.texture3ID > materialManager.TextureNames.Count - 1)
                this.texture3ID = 0;

            {
                throw new NotImplementedException("C11 syndicate plugin must created!");
                // return new MyEngine.Material(materialManager.TextureNames[(int)this.texture1ID], materialManager.TextureNames[(int)this.texture2ID], materialManager.TextureNames[(int)this.texture3ID], (EnumMappingMode)this.mappingMode);
            }
        }

        public override string ToString()
        {
            return string.Format("T1: {0}, T2: {1}, T3: {2}, Mappint: {3}", texture1ID, texture2ID, texture3ID, mappingMode);
        }

        #endregion Public Methods

        #region Private Methods

        private void UpdateHashCode()
        {
            AdlerChecksum adler = new AdlerChecksum();
            byte[] byteArray = new byte[60];
            BitConverter.GetBytes(this.texture1ID).CopyTo(byteArray, 0);
            BitConverter.GetBytes(this.texture2ID).CopyTo(byteArray, 2);
            BitConverter.GetBytes(this.texture3ID).CopyTo(byteArray, 4);
            BitConverter.GetBytes(this.data1).CopyTo(byteArray, 6);
            BitConverter.GetBytes(this.data2).CopyTo(byteArray, 8);
            BitConverter.GetBytes(this.data3).CopyTo(byteArray, 10);
            BitConverter.GetBytes(this.data4).CopyTo(byteArray, 12);
            BitConverter.GetBytes(this.mappingMode).CopyTo(byteArray, 14);
            BitConverter.GetBytes(this.mappingMatrix3x3.M11).CopyTo(byteArray, 16);
            BitConverter.GetBytes(this.mappingMatrix3x3.M12).CopyTo(byteArray, 20);
            BitConverter.GetBytes(this.mappingMatrix3x3.M13).CopyTo(byteArray, 24);
            BitConverter.GetBytes(this.mappingMatrix3x3.M21).CopyTo(byteArray, 28);
            BitConverter.GetBytes(this.mappingMatrix3x3.M22).CopyTo(byteArray, 32);
            BitConverter.GetBytes(this.mappingMatrix3x3.M23).CopyTo(byteArray, 36);
            BitConverter.GetBytes(this.mappingMatrix3x3.M31).CopyTo(byteArray, 40);
            BitConverter.GetBytes(this.mappingMatrix3x3.M32).CopyTo(byteArray, 44);
            BitConverter.GetBytes(this.mappingMatrix3x3.M33).CopyTo(byteArray, 48);
            BitConverter.GetBytes(this.data5).CopyTo(byteArray, 52);
            BitConverter.GetBytes(this.data6).CopyTo(byteArray, 56);

            adler.MakeForBuff(byteArray);
            this.hashcode = (int)adler.ChecksumValue;
        }

        #endregion Private Methods
    }
}